/**
*  \file contactor.h

*  \author Michael J. Hohmann  michael.hohmann@linde-mh.de
*
*  \brief Contactor Control
*    
*   Compatibility
*   =============
*
*  | compatibility |         |
*  | ------------- | ------- |
*  | endianes      | generic |
*  | cpu           | generic |
*  | compiler      | generic |
*
*
*  Resource Estimation 
*  ===================
*
*  | Resource Estimation |           |
*  | ------------------- | --------- |
*  | nvram               | none      |
*  | rom                 | 2 KB      |
*  | ram                 | none      |
*  | stack               | 50 bytes |
*
*   Overall Function
*   ================
*   This unit is intended to control a relay/contactor via an PWM output.
*   The PWM-value will be calculated as function of the supply voltage.
*   Therefore two interpolation tables have to be passed to the constructor.
*   The tighten table is used until the contactor was closed. To hold the contactor the hold curve is used.
*
*   Dynamic behavior
*   ================
*   It is expected that the function contactor_construct() is called once at the initialization phase of the system.
*   The function contactor_service() is expected to be called cyclically with an period of 1-100ms.
*   The function contactor_clear_error() and contactor_get_status() can be called from any interrupt level at any time.
*
*   Interrupts
*   ==========
*   No Interrupts are used. 
*
*   States machine
*   ==============

  @startuml

  [*]					  --> contactor_state_release : Initial State
  contactor_state_release --> contactor_state_tighten : T1\ncontactor_on == TRUE
  contactor_state_release --> contactor_state_release : T9
  contactor_state_release                             : state_time = 0

  contactor_state_tighten --> contactor_state_release : T2\ncontactor_on==TRUE\nor\nPWM==0
  contactor_state_tighten --> contactor_state_tighten : T10
  contactor_state_tighten --> contactor_state_hold    : T3\n state_time > on_ticks
  contactor_state_tighten --> contactor_state_error   : T4\nPWM == 0
  contactor_state_tighten                             : state_time ++

  contactor_state_hold    --> contactor_state_hold    : T11
  contactor_state_hold    --> contactor_state_release : T5\ncontactor_on == FALSE

  contactor_state_error   --> contactor_state_error   : T12
  contactor_state_error   --> contactor_state_release : T8\n reset_error==TRUE
 @enduml
*/

#ifndef CONTACTOR_H_INCLUDED
#define CONTACTOR_H_INCLUDED

/*================================================[ public includes  ]================================================*/
#include "../cfg/prj.h"
#include "../interpol/interpol_u16_u16.h"

/*================================================[ public defines   ]================================================*/

/*================================================[ public datatypes ]================================================*/
/** Contactor States
* List of internal states of the state machine.
**/
enum contactor_state
{
   contactor_state_invalid, /**< This state indicate that the object is not valid */
   contactor_state_release, /**< Release the contactor. In this state the contactor is off (PWM output =0 ) */
   contactor_state_tighten, /**< Tighten the contactor. In this state The tighten curve is used to calculate the PWM value.*/
   contactor_state_hold,    /**< Hold the contactor. In this state the hold curve is used. */
   contactor_state_error    /**< This state will be entered if an over or under voltage occured */
};

/** Object definition.
* 
*  The struct contactor_object contain the member variables of an instance of the contactor object.
*  It is unwanted to access any member of this struct directly.
*/
struct contactor_obj
{   
   struct interpol_u16_u16_obj  const *tighten_table;   /**< tigthen_table for interpolation            */
   struct interpol_u16_u16_obj  const *hold_table;      /**< hold_table for interpolation               */
   U16 on_ticks;                                        /**< time where the tighten curve is active     */
   BO reset_error;  /**< This flag will be set by the function contactor_clear_error.                   */
   struct interpol_u16_u16_obj const * current_table; /** pointer to currently active table             */
   U16 tighten_counter; /**< counter to count how much time elapse after the tighten curve is active    */
   enum contactor_state current_state;  /**< true mean closed, false means open                         */
};

/*================================================[ public variables ]================================================*/

/*================================================[ inline functions ]================================================*/

/*================================================[ public functions ]================================================*/

/** Constructor.
*
*  Construct the contactor object.
*
*  \param [in    ] me          Object pointer. NIL will trigger an assert.
*  \param [in    ] pwm_tighten Pointer to an interpol_u16_u16_obj object. NIL will trigger an assert.
*  \param [in    ] pwm_hold    Pointer to an interpol_u16_u16_obj object. NIL will trigger an assert.
*  \param [in    ] on_ticks    Time in ticks until the tighten curve is active.
*
*  \return Always returns RC_SUCCESS
*/
RC contactor_construct(
   struct contactor_obj *me,
   struct interpol_u16_u16_obj const *pwm_tighten,
   struct interpol_u16_u16_obj const *pwm_hold,
   U16 on_ticks );

/** Contactor service
*
*  This function will service the internal state machine and return the PWM value for the contactor.
*  It is expected that this function is called cyclicly for example every 10ms.
*  The return value of the function should be passed to the function that controll the PWM output of the contactor.
*
*  \param  [in    ] me            Object pointer. NIL will trigger an assert.
*  \param  [in    ] voltage       The current supply voltage.
*  \param  [in    ] contactor_on  Control the contactor. 
*                                 - TRUE switch contactor on
*                                 - FALSE switch contactor off
*
*  \return PWM value to control the contactor
*/
U16 contactor_service( struct contactor_obj *me, U16 voltage, BO contactor_on );

/**  Clear Error.
*
*  If an over or under voltage was detected. The contactor will switch off and stay in this status until this function is called.
*
*  \param  [in    ] me Object pointer. NULL will throw an assert.
*/
void contactor_clear_error(struct contactor_obj *me );

/** Get status of contactor
*
*  Get the current state of contactor.
*
*  \param [in    ] me    Object pointer. NULL will throw an assert.
*  \param [   out] state Retrieve the current state of the state machine. It's save to pass NIL if the value is not needed.
*
*  \return      The return value can be:
*               - TRUE contactor is currently closed
*               - FALSE contactor is currently opened
*/
BO contactor_get_status(struct contactor_obj const*me , enum contactor_state *state);

/*====================================================================================================================*/

#endif

/***********************************************************************************************************************
*                             Copyright 2018 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
